Telegram Group & Telegram Channel
🐹 Задача с подвохом: Generics и интерфейсы (Go 1.24)

Условие:

Что выведет следующий код и почему?


package main

import (
"fmt"
)

type Stringer interface {
String() string
}

type MyInt int

func (m MyInt) String() string {
return fmt.Sprintf("MyInt: %d", m)
}

func printValue[T any](val T) {
var s Stringer
if v, ok := any(val).(Stringer); ok {
s = v
}
if s != nil {
fmt.Println("Stringer:", s.String())
} else {
fmt.Println("Default:", val)
}
}

func main() {
var x MyInt = 5
printValue(x)
printValue(10)
}


Вопрос:
Что будет напечатано? Почему результат может удивить даже опытных Go-разработчиков?

🔍 Разбор:

Этот код использует generics и проверяет, реализует ли
val интерфейс Stringer.

Пошагово:

1️⃣
var x MyInt = 5
Тип
MyInt реализует интерфейс Stringer через метод:

```go
func (m MyInt) String() string { ... }
```

2️⃣
printValue(x)
-
val здесь типа MyInt.
- В строке:
any(val).(Stringer)
- Приведение типа успешно, потому что
MyInt реализует Stringer.
- Печатается:
```
Stringer: MyInt: 5
```

3️⃣
printValue(10)
- Тип
val здесь int.
-
int не реализует Stringer.
- Приведение
any(val).(Stringer) не срабатывает (ok == false).
- Печатается:
```
Default: 10
```

Ожидаемый вывод:

```
Stringer: MyInt: 5
Default: 10
```

💥 Подвох:

- Даже если
MyInt — это просто int, метод String() делает его другим типом, который реализует интерфейс.
- Многие забывают, что встроенные типы (int, string, и т.д.) никогда не реализуют интерфейсы напрямую, даже если они похожи на пользовательские типы.
- Ключевой момент:
any(val) оборачивает значение в интерфейс{}, поэтому приведение типа срабатывает только если исходный тип действительно реализует интерфейс.

🆕 Почему это актуально для Go 1.24:

Generics в Go 1.22+ улучшились по типовой проверке и стали более гибкими. Go 1.24 сделал generics более стабильными и оптимизированными, но все еще важно понимать различия между типами и интерфейсами, особенно при работе с
any и приведения типов внутри параметризованных функций.

🛡️ Лайфхак:

Если вы хотите печатать всё одинаково для типов с
String(), можно сделать generic-констрейн с интерфейсом:

```go
func printValue2[T fmt.Stringer](val T) {
fmt.Println("Stringer (generic):", val.String())
}
```

Вывод:

Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между
int и MyInt влияют на поведение программы.



tg-me.com/golangtests/773
Create:
Last Update:

🐹 Задача с подвохом: Generics и интерфейсы (Go 1.24)

Условие:

Что выведет следующий код и почему?


package main

import (
"fmt"
)

type Stringer interface {
String() string
}

type MyInt int

func (m MyInt) String() string {
return fmt.Sprintf("MyInt: %d", m)
}

func printValue[T any](val T) {
var s Stringer
if v, ok := any(val).(Stringer); ok {
s = v
}
if s != nil {
fmt.Println("Stringer:", s.String())
} else {
fmt.Println("Default:", val)
}
}

func main() {
var x MyInt = 5
printValue(x)
printValue(10)
}


Вопрос:
Что будет напечатано? Почему результат может удивить даже опытных Go-разработчиков?

🔍 Разбор:

Этот код использует generics и проверяет, реализует ли
val интерфейс Stringer.

Пошагово:

1️⃣
var x MyInt = 5
Тип
MyInt реализует интерфейс Stringer через метод:

```go
func (m MyInt) String() string { ... }
```

2️⃣
printValue(x)
-
val здесь типа MyInt.
- В строке:
any(val).(Stringer)
- Приведение типа успешно, потому что
MyInt реализует Stringer.
- Печатается:
```
Stringer: MyInt: 5
```

3️⃣
printValue(10)
- Тип
val здесь int.
-
int не реализует Stringer.
- Приведение
any(val).(Stringer) не срабатывает (ok == false).
- Печатается:
```
Default: 10
```

Ожидаемый вывод:

```
Stringer: MyInt: 5
Default: 10
```

💥 Подвох:

- Даже если
MyInt — это просто int, метод String() делает его другим типом, который реализует интерфейс.
- Многие забывают, что встроенные типы (int, string, и т.д.) никогда не реализуют интерфейсы напрямую, даже если они похожи на пользовательские типы.
- Ключевой момент:
any(val) оборачивает значение в интерфейс{}, поэтому приведение типа срабатывает только если исходный тип действительно реализует интерфейс.

🆕 Почему это актуально для Go 1.24:

Generics в Go 1.22+ улучшились по типовой проверке и стали более гибкими. Go 1.24 сделал generics более стабильными и оптимизированными, но все еще важно понимать различия между типами и интерфейсами, особенно при работе с
any и приведения типов внутри параметризованных функций.

🛡️ Лайфхак:

Если вы хотите печатать всё одинаково для типов с
String(), можно сделать generic-констрейн с интерфейсом:

```go
func printValue2[T fmt.Stringer](val T) {
fmt.Println("Stringer (generic):", val.String())
}
```

Вывод:

Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между
int и MyInt влияют на поведение программы.

BY Go tests


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/golangtests/773

View MORE
Open in Telegram


Go tests Telegram | DID YOU KNOW?

Date: |

How Does Telegram Make Money?

Telegram is a free app and runs on donations. According to a blog on the telegram: We believe in fast and secure messaging that is also 100% free. Pavel Durov, who shares our vision, supplied Telegram with a generous donation, so we have quite enough money for the time being. If Telegram runs out, we will introduce non-essential paid options to support the infrastructure and finance developer salaries. But making profits will never be an end-goal for Telegram.

Newly uncovered hack campaign in Telegram

The campaign, which security firm Check Point has named Rampant Kitten, comprises two main components, one for Windows and the other for Android. Rampant Kitten’s objective is to steal Telegram messages, passwords, and two-factor authentication codes sent by SMS and then also take screenshots and record sounds within earshot of an infected phone, the researchers said in a post published on Friday.

Go tests from sg


Telegram Go tests
FROM USA